package cn.sylinx.common.ext.vertx;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

import cn.hutool.core.lang.Filter;
import cn.hutool.core.util.ClassUtil;
import cn.sylinx.common.ext.log.GLog;
import cn.sylinx.common.lang.StringUtil;
import io.vertx.core.DeploymentOptions;
import io.vertx.core.Verticle;

public class VerticleRegistry {

	public void register(String pkgList) {

		Set<Class<?>> clzSet = scan(pkgList);
		for (Class<?> clz : clzSet) {
			boolean bl = deployOneVerticle(clz);
			if (!bl) {
				GLog.error("发布verticle失败,class:{}", clz.getName());
			}
		}

	}

	public boolean register(Class<?> clz) {
		return deployOneVerticle(clz);
	}

	private boolean deployOneVerticle(Class<?> clz) {

		if (!isVerticle(clz)) {
			GLog.error("非Verticle, class:{}", clz.getName());
			return false;
		}

		VerticleClass vc = clz.getDeclaredAnnotation(VerticleClass.class);
		boolean blocking = vc.blocking();
		
		try {
			Verticle verticle = (Verticle) clz.newInstance();
			if(blocking) {
				VertxHolder.get().vertx().deployVerticle(verticle, new DeploymentOptions().setWorker(true));
			} else {
				VertxHolder.get().vertx().deployVerticle(verticle);
			}
			GLog.info("Verticle:{} 发布成功", (StringUtil.isBlank(vc.value()) ? verticle.getClass() : vc.value()));
		} catch (InstantiationException | IllegalAccessException e) {
			GLog.error("Verticle发布异常", e);
			return false;
		}

		return true;
	}

	private Set<Class<?>> scan(String scanPackageList) {

		String pkgList = Optional.ofNullable(scanPackageList).orElse(null);
		Set<Class<?>> clzSet = new HashSet<>();
		if (StringUtil.isBlank(pkgList)) {
			return clzSet;
		}

		String[] pkgAry = pkgList.split(",");
		for (String pkg : pkgAry) {
			if (StringUtil.isNotBlank(pkg)) {
				Set<Class<?>> dbset = scanOnePackage(pkg);
				clzSet.addAll(dbset);
			}
		}

		return clzSet;
	}

	private Set<Class<?>> scanOnePackage(String scanPackage) {

		String doScanPackage = scanPackage;
		return ClassUtil.scanPackage(doScanPackage, new Filter<Class<?>>() {
			@Override
			public boolean accept(Class<?> clazz) {
				return isVerticle(clazz);
			}
		});
	}

	private boolean isVerticle(Class<?> clazz) {
		return clazz.getDeclaredAnnotation(VerticleClass.class) != null && Verticle.class.isAssignableFrom(clazz);
	}
}